((window) =>{
    const PENDING = 'pending'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    function Promise(excutor){
        this.state = PENDING
        this.data = undefined
        this.callbacks = [];
        const self = this
        function resolve(value){
            if(self.state !== PENDING) return
            self.state = 'fulfilled'
            self.data = value
            if(self.callbacks.length > 0){
            setTimeout(() => {
                self.callbacks.forEach(callbacks=>callbackObj.resolve(value))
            }, 0);
            }
        }
        function reject(reason){
            if(self.state !== PENDING) return
            self.state = 'rejected'
            self.data = reason
            if(self.callbacks.length > 0){
            setTimeout(() => {
                self.callbacks.forEach(callbackObj => callbackObj.reject(reason))
            }, 0);
            }
        }
            try{
                excutor(resolve,reject)
            }catch(error){
                reject(error)
            }
    }
        Promise.prototype.then = function(onResolved,onRejected){
            const self =this
            onResolved = typeof onResolved==='function'? onResolved : value=>value
            onRejected = typeof onRejected==='function'? onRejected : reason =>{throw reason}
            return new Promise((resolve,reject)=>{
                function handle(callback){
                    try{
                    const result = callback(self.data)
                    if(result === Promise){
                        result.then(
                            value => value,
                            reason => reason
                        )
                    }else{
                        resolve(value)
                    }
                }catch(error){
                    reject(error)
                }
                }
            })
        }
        if(self.state === FULFILLED){
            setTimeout(() => {
                handle(onResolved)
            }, 0);
        }else if(self.state === REJECTED){
            setTimeout(() => {
                handle(onRejected)
            }, 0);
        }else{
        self.callbacks.push({
            resolved : ()=>handle(onResolved),
            rejected : ()=> handle(onRejected)
        })            
        }
window.Promise = Promise
})(window)